<template>
  <Select
    :value="getVal"
    filterable
    v-bind="$attrs"
    :multiple="props.multiple"
    :filter-method="filterMethod"
    @change="handleChange"
    @focus="handleFocus"
  >
    <vxe-list height="200" class="v-list-container" :data="options" auto-resize>
      <template #default="{ items }">
        <Option
          v-for="item in items"
          :key="item.value"
          :label="item.label"
          :value="item.value"
          v-bind="item"
        />
      </template>
    </vxe-list>
  </Select>
</template>

<script setup name="basic-select">
import { ref, unref, computed, watch } from 'vue'
import { Select, Option } from 'element-ui'
import { get, cloneDeep } from 'lodash-es'
import { isEmpty } from '@/utils/format'

const props = defineProps({
  value: {
    type: [String, Array, Number],
    default: ''
  },
  options: {
    type: Array,
    default: () => []
  },
  fieldNames: {
    type: Object,
    default: () => ({ label: 'label', value: 'value' })
  },
  multiple: {
    type: Boolean,
    default: false
  }
})
const emit = defineEmits(['options-change', 'update:value'])

const val = ref(props.value)
const options = ref([])
const mockData = ref([])

const getVal = computed(() => {
  if (props.multiple && unref(val)?.length) {
    return unref(val).map(item => item[props.fieldNames.value])
  }
  return unref(val) ?? ''
})

watch(
  [() => props.value, () => props.options],
  ([v, data]) => {
    val.value = v
    const result = filterOptions(data)
    mockData.value = cloneDeep(result)
    if (!isEmpty(v) && data.length) {
      options.value = result.filter(item => item.value === v)
    } else {
      options.value = result
    }
  },
  { immediate: true }
)

function filterMethod(e) {
  options.value = e ? unref(mockData).filter((item) => item.label.includes(e)) : unref(mockData)
}

function handleFocus() {
  if (!isEmpty(unref(val)) && unref(mockData).length) {
    const index = unref(mockData).findIndex(item => item.value === unref(val))
    options.value = unref(mockData).slice(index)
  }
}

function handleChange(e) {
  val.value = e
  emit('options-change', e)
  emit('update:value', e)
}

function filterOptions(data) {
  const { label: labelField, value: valField } = props.fieldNames
  return data.map(item => {
    const label = get(item, labelField)
    const value = get(item, valField)
    return { label, value }
  })
}
</script>

<style lang="scss">
::v-deep {
  .el-select {
    width: 100% !important;
  }
}
</style>
